home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
-
- FMR version Makeing by ken 89.9.5
-
- ***************************************************************************/
- #include <stdio.h>
- #include <time.h>
- #include <string.h>
- #include <fmc.h>
-
- #define unlink remove
-
- typedef long TIME_T;
-
- extern int port,bps;
- extern unsigned char *cvram;
-
- extern void Send_Failure();
- extern TIME_T gtime();
- extern int kbhit();
- extern int getch();
- extern void wrtstr();
- extern void Dmy_form();
- extern void Dsp_vram();
-
- TIME_T gtime(rt)
- long *rt;
- {
- long l;
- /*************************************************************
- time_t t;
- struct tm *dmy;
-
- time(&t);
- dmy = localtime(&t);
- l = dmy->tm_sec + dmy->tm_min * 60 + dmy->tm_hour * 3600;
- **************************************************************/
- l = clock() / CLK_TCK;
- if ( rt != NULL )
- *rt = l;
- return l;
- }
- int Async_BuffeR_Check( chx )
- unsigned char *chx;
- {
- int data,len;
- unsigned int status;
-
- RSB_read(port,&len);
- if ( len != 0 ) {
- RSB_receive(port,&data,&status);
- *chx = data;
- }
- return len;
- }
- void Async_Send(chx)
- int chx;
- {
- unsigned int status;
-
- RSB_send(port,chx,&status);
- }
- int ST_Check_Abort()
- {
- if ( kbhit() != 0 && getch() == '\x1B' )
- return 1;
- return 0;
- }
- void ST_Yes_or_No(arg,yn)
- char *arg;
- char *yn;
- {
- wrtstr(arg,17,20,0x02);
- *yn = getch();
- }
- void ST_Initialize()
- {
- int i;
- char tmp[160];
- static char *menu[]={
- "Msg ","File ","UpDow ","Type ","ComSent ",
- "DataSent","ErrSent ","PacSent ","ComRate ","DataRate",
- "Elapsed ",
- " "," ","ComRead ","DataRead","ErrRead ",
- "PacRead ","UplSize ","DowSize ","UplRem ","DowRem ",
- "RemTime " };
-
- Dmy_form(tmp,50,0x98,0x95,0x99);
- wrtstr(tmp,15,7,0x06);
-
- Dmy_form(tmp,50,0x96,0x20,0x96);
- for ( i = 0 ; i < 13 ; i++ )
- wrtstr(tmp,15,8+i,0x06);
-
- Dmy_form(tmp,50,0x9A,0x95,0x9B);
- wrtstr(tmp,15,21,0x06);
-
- wrtstr(" <<< B Plus Protocol(SM) Abort Hit ESC Key >>>",17,8,0x02);
-
- for ( i = 0 ; i < 22 ; i++ )
- wrtstr(menu[i],17+(i/11)*24,9+(i%11),0x06);
- }
- void ST_Terminate()
- {
- Dsp_vram(cvram);
- }
- void ST_Display_String(no,str)
- int no;
- char *str;
- {
- wrtstr(str,27+(no/18)*24,9+(no%18),0x06);
- }
- void ST_Display_Value(no,val)
- int no;
- long val;
- {
- char tmp[20];
-
- sprintf(tmp,"%7ld",val);
- ST_Display_String(no,tmp);
- }
- #define STMsg 0
- #define STFile 1
- #define STUpDow 2
- #define STType 3
- #define STComSent 4
- #define STDataSent 5
- #define STErrSent 6
- #define STPacSent 7
- #define STComRate 8
- #define STDataRate 9
- #define STElapsed 10
-
- #define STComRead 20
- #define STDataRead 21
- #define STErrRead 22
- #define STPacRead 23
- #define STUplSize 24
- #define STDowSize 25
- #define STUplRem 26
- #define STDowRem 27
- #define STRemTime 28
- /***********************************************************************/
- /****
- BPLUS.INC - B Plus Protocol Support routines
- (derived from BPROTO.INC)
-
- Copyright 1987, CompuServe Incorporated
-
- These routines may be used as-is or in modified form in any
- personal computer terminal program to implement support of the
- CompuServe B and B Plus Protocols for the purpose of transfering
- information between CompuServe hosts and a personal computer.
-
- No warranty, expressed or implied, covers this code, or the specifications
- of the B and B Plus Protocols.
-
-
- Last update:
- Russ Ranshaw 16-Dec-87 Corrected Upload Abort problems.
- Russ Ranshaw 07-Apr-88 Corrected additional Abort problems.
- Russ Ranshaw 09-Apr-88 Added Quote Set to + Packet.
- Russ Ranshaw 10-Apr-88 Added Download Resume.
- Russ Ranshaw 22-Apr-88 Added File Information to Download.
- (File length only.)
- Russ Ranshaw 11-May-88 Added check to control Upload degradation
- under Send Ahead.
- Russ Ranshaw 16-May-88 Remove debugging code for release
- of Version 2.1
- Russ Ranshaw 01-Jun-88 Added externally settable file size for
- Downloads. Use ST_Yes_or_No instead of
- ST_Prompt to get Y/N response.
- Russ Ranshaw 07-Jun-88 Added defensive check to see if Aborting
- is already true. Changed comm. rate
- calculation.
- Russ Ranshaw 23-Jun-88 Add check for <DLE><B> in ReSync.
- Russ Ranshaw 04-Aug-88 Added WACK intercept to update the
-
- status display, mostly so that resumes
- show some activity while the host calculates
- it's CRC value.
- Paul Resch 28-Aug-88 Converted to standard C code.
- ****/
-
- /****************
- **
- ** This module implements the B-Protocol Functions.
- **
- **
- ** If you have any questions, contact:
- ** Russ Ranshaw, CompuServe Incorporated
- ** [70000,1010]
- **
- ** This source was originally derived from BP.C, written by
- ** Steve Wilhite, CompuServe Incorporated.
- **
- *****************/
-
- /*
- const
- UnitVersion = "2.2c";
- UnitVerDate = "04 Aug 88";
- UnitUpdBy = "RWR";
- */
-
- /****************************************************************************/
- /*
- * C implementation notes:
- * Routines with names beginning "ST_" are not supplied. They are
- * strictly console I/O. Implement as needed, or see the PASCAL
- * version.
- * "Async_Send" is an extern that is passed a byte for output to the
- * serial port.
- * "Async_BuffeR_Read" is an extern that is passed the address of a byte.
- * If TRUE is returned, the byte will be from the serial port.
- * If FALSE is returned, the byte value is undefined.
- * The CRC subroutines are included in this module.
- *
- * I have tried to keep as close as possible to Mr. Ranshaw's structure.
- * Please see the PASCAL source to clarify any confusion.
- */
- /****************************************************************************/
-
- #ifdef DEBUG
- #define STATIC
- #else
- #define STATIC static
- #endif
-
- #define TRUE 1
- #define FALSE 0
-
- STATIC TIME_T e_timer;
-
- typedef char maxstr[256];
-
- int BP_Auto_Resume = FALSE; /* True to automatically attempt transfer */
- /* resumption if the Initiator can do it */
- int BP_Use_File_Size = FALSE;
- long BP_File_Size=0;
- /* BP_Quote_This is invoked to set bits in BP_Special_Quote_Set. */
- /* It must be called prior to calling BP_DLE_Seen for each character in the */
- /* ranges 0x00 -> 0x1f and 0x80 -> 0x9f that is to be quoted. */
- /* BP_Quote_This (int Value); */
-
- /* BP_Term_ENQ is invoked when Terminal Mode receives <ENQ> from host */
- /* BP_Term_ENQ(); */
-
- /* BP_Term_ESC_I is invoked when Terminal Mode receives <ESC><I> from host */
- /* BP_Term_ESC_I (maxstr ESC_I_Response); */
-
- /* BP_DLE_Seen is invoked when Terminal Mode receives <DLE> from host */
- /* BP_DLE_Seen(); */
-
- /*===========================================================================*/
-
- typedef unsigned char QS_Array[8];
- typedef unsigned char QS_Array_p;
-
- #define bps300 0
- #define bps600 1
- #define bps1200 2
- #define bps2400 3
- #define bps4800 4
- #define bps9600 5
- int PortBps = bps2400;
-
- STATIC int seq_num; /* Current Sequence Number - init by Term_ENQ */
- STATIC unsigned short checksum; /* May hold CRC */
-
- /* Initiator's Parameters */
- STATIC unsigned char His_WS, /* Initiator's Window Send */
- His_WR, /* Initiator's Window Receive */
- His_BS, /* Initiator's Block Size */
- His_CM; /* Initiator's Check Method */
- STATIC QS_Array His_QS; /* Initiator's Quote Set */
- /* The next 3 Parameters are for the B Plus File Transfer Application */
- STATIC unsigned char His_DR=0, /* Initiator's Download Recovery Option */
- His_UR=0, /* Initiator's Upload Recovery Option */
- His_FI=0; /* Initiator's File Information Option */
-
- /* Negotiated Parameters */
- STATIC unsigned char Our_WS=0, /* Negotiated Window Send */
- Our_WR=0, /* Negotiated Window Receive */
- Our_BS=0, /* Negotiated Block Size */
- Our_CM=0; /* Negotiated Check Method */
- STATIC QS_Array Our_QS; /* Our Quote Set */
- STATIC unsigned char Our_DR=0, /* Our Download Recovery Option */
- Our_UR=0, /* Our Upload Recovery Option */
- Our_FI=0, /* Our File Information Option */
- Def_DR=0, /* User's preferred DOW Resume option */
- Def_BS=0; /* Default Block Size: varies depending */
- /* on the baud in use */
- STATIC unsigned char Port_Update_Rate=0;
- /* Number of port bytes between Status */
- /* upldates for the Port */
- STATIC int B_Plus=0; /* True if B Plus in effect */
- STATIC int Use_CRC=0; /* True if CRC in effect */
- STATIC int BP_Special_Quoting = 0;/* True to use BP_Special_Quote_Set */
- STATIC QS_Array BP_Special_Quote_Set = /* User's specified Quote Set */
- {0x14, 0x00, 0xd4, 0x00, /* ETX ENQ DLE XON XOFF NAK */
- 0x00, 0x00, 0x00, 0x00
- };
-
- STATIC int Buffer_Size=0; /* Our_BS * 4 */
- STATIC int SA_Max=0; /* 1 if SA not enabled, else Max_SA */
- STATIC int SA_Error_Count=0; /* # of times S_Send_Data called */
-
- STATIC unsigned char Quote_Table[256]; /* The quoting table */
-
- STATIC QS_Array DQ_Full =
- {0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff
- };
- STATIC QS_Array DQ_Default =
- {0x14, 0x00, 0xd4, 0x00, /* ETX ENQ DLE XON XOFF NAK */
- 0x00, 0x00, 0x00, 0x00
- };
- STATIC QS_Array DQ_Minimal =
- {0x14, 0x00, 0xd4, 0x00, /* ETX ENQ DLE XON XOFF NAK */
- 0x00, 0x00, 0x00, 0x00
- };
- STATIC QS_Array DQ_Extended =
- {0x14, 0x00, 0xd4, 0x00, /* ETX ENQ DLE XON XOFF NAK */
- 0x00, 0x00, 0x50, 0x00 /* XON XOFF */
- };
-
- #define Max_Buf_Size 1032 /* Largest data block we can handle */
- #define Max_SA 2 /* Maximum number of waiting Packets */
-
- #define Def_Buf_Size 511 /* Default data block */
- #define Def_WS 1 /* I can send 2 Packets ahead */
- #define Def_WR 1 /* I can receive single send-ahead */
- #define Def_CM 1 /* I can handle CRC */
- #define Def_DQ 1 /* I can handle non-quoted NUL */
- /* (including the `Tf' Packet */
- #define Def_UR 0 /* I can NOT handle Upload Recovery */
- #define Def_FI 1 /* I can handle File Information */
-
- #define max_Errors 10
-
-
- /* Receive States */
-
- #define R_Get_DLE 0
- #define R_Get_B 1
- #define R_Get_Seq 2
- #define R_Get_Data 3
- #define R_Get_Check 4
- #define R_Send_ACK 5
- #define R_Timed_Out 6
- #define R_Success 7
-
- /* Send States */
-
- #define S_Get_DLE 1
- #define S_Get_Num 2
- #define S_Have_ACK 3
- #define S_Get_Packet 4
- #define S_Skip_Packet 5
- #define S_Timed_Out 6
- #define S_Send_NAK 7
- #define S_Send_ENQ 8
- #define S_Send_Data 9
-
- /* Other Constants */
-
- #define dle 16
- #define etx 03
- #define nak 21
- #define enq 05
-
- typedef char lstr[256];
- typedef struct {
- int seq; /* Packet's sequence number */
- int num; /* Number of bytes in Packet */
- unsigned char buf[Max_Buf_Size]; /* Actual Packet data */
- } buf_type;
-
- /****************************************************************************/
- void ltoa( n, s )
- register long n;
- register char *s;
- {
- register char *t;
- register long i;
- register char c;
- long sign;
- long divten;
-
- if( (sign = n) < 0 )
- n = -n;
- t = s;
- do
- {
- i = (divten = (n / 10)) * 10; /* get ones digit (sigh) */
-
- *t++ = ( n - i ) + '0';
- } while( (n = divten) > 0 );
- if( sign < 0 )
- *t++ = '-';
- *t-- = '\0';
- while( s < t )
- {
- c = *t;
- *t-- = *s;
- *s++ = c;
- }
- }
- /****************************************************************************/
- /*
- Clear_Quote_Table:
- Initialize Quote_Table to all zeros (nothing quoted).
- */
-
- STATIC void Clear_Quote_Table()
- {
- int i;
-
-
- for( i = 0; i<=255; i++ )
- Quote_Table [i] = 0;
- }
-
- /*
- Update_Quote_Table:
- Sets the i-th entry of Quote_Table to the necessary quoting character
- according to the i-th bit of the supplied Quote Set.
- */
-
- STATIC void Update_Quote_Table (Quote_Set)
- QS_Array_p *Quote_Set;
- {
- int i, j, k;
- unsigned char b, c;
-
- k = 0;
- c = 0x40;
-
- for( i = 0; i<=7; i++ )
- {
- if( i == 4 )
- /* Switch to upper control set */
- {
- c = 0x60;
- k = 128;
- }
-
- b = Quote_Set [i];
-
- for (j = 0; j<=7; j++ )
- {
- if ((b & 0x80) != 0)
- Quote_Table [k] = c;
-
- b = b << 1;
- c = c + 1;
- k = k + 1;
- }
- }
- }
-
- /* BP_Quote_This sets bits in BP_Special_Quote_Set. */
- /* It sets BP_Special_Quoting true to use the special quote set. */
- /* If Value = -1, the Special Quote Set is restored to its default. */
-
- void BP_Quote_This (Value)
- int Value;
- {
- int i, j;
-
- if ((Value >= 0x00 && Value <= 0x1F) ||
- (Value >= 0x80 && Value <= 0x9f) )
- {
- if (Value > 0x1f)
- {
- i = 4;
- Value = Value & 0x1f;
- }
- else
- i = 0;
-
- i = i + Value / 8; /* = index into BP_Special_Quote_Set */
- j = Value % 8; /* = Bit number in the i-th byte */
- BP_Special_Quote_Set [i] =
- BP_Special_Quote_Set [i] || (0x80 >> j);
- BP_Special_Quoting = TRUE;
- }
- else if (Value == -1) /* Restore the Quote Set? */
- {
- for( i=0; i<sizeof(DQ_Minimal); i++ )
- BP_Special_Quote_Set[i] = DQ_Minimal[i];
- BP_Special_Quoting = FALSE;
- }
- }
-
- /*
- BP_Term_ENQ is called when the terminal emulator receives the character <ENQ>
- from the host. Its purpose is to initialize for B Protocol and tell the
- host that we support B Plus.
- */
-
-
- void BP_Term_ENQ()
- {
- int i;
-
- seq_num = 0;
- Buffer_Size = 512; /* Set up defaults */
- Our_WS = 0;
- Our_WR = 0;
- Our_BS = 4;
- Our_CM = 0;
- Our_DR = 0;
- Our_UR = 0;
- Our_FI = 0;
-
- B_Plus = FALSE; /* Not B Plus Protocol */
- Use_CRC = FALSE; /* Not CRC_16 */
- SA_Max = 1; /* Single Packet send */
- SA_Error_Count = 0; /* No Upload errors yet */
-
- /* Set up Our prefered Quoting Mask */
- for( i=0; i<sizeof(DQ_Minimal); i++ )
- Our_QS[i] = DQ_Minimal[i];
-
- Clear_Quote_Table();
- Update_Quote_Table (Our_QS);
-
- Async_Send (dle);
- Async_Send ('+');
- Async_Send ('+');
- Async_Send (dle);
- Async_Send ('0');
- }
-
- /*
- BP_Term_ESC_I is called when <ESC><I> is received by the terminal emulator.
- Note that CompuServe now recognizes the string ",+xxxx" as the final field.
- THis provides a checksum (xxxx being the ASCII decimal representation of the
- sum of all characters in the response string from # to +. The purpose of
- the checksum is to eliminate the need for retransmission and comparison of
- the response.
- */
-
-
- void BP_Term_ESC_I (esc_I_Response)
- char esc_I_Response[];
- {
- int i;
- maxstr t;
- int cks; /* checksum */
-
- cks = 0;
-
- for (i = 0; i<strlen (esc_I_Response); i++ )
- {
- Async_Send (esc_I_Response [i]);
- cks += esc_I_Response [i];
- }
-
- Async_Send (',');
- Async_Send ('+');
- cks = cks + ',' + '+';
-
- ltoa( (long)cks, t );
-
- i = 4 - strlen( t ); /* zero-fill */
- while( i-- )
- Async_Send( '0' );
-
- for (i = 0; i<strlen (t); i++ )
- Async_Send (t [i]);
-
- Async_Send (0x0d); /* <CR> */
- }
-
-
- /*
- BP_DLE_Seen is called from the main program when the character <DLE> is
- received from the host.
-
- This routine calls Read_Packet and dispatches to the appropriate
- handler for the incoming Packet.
- */
-
-
- STATIC int ttime=0,
- R_Size=0, /* size of receiver buffer */
- ch=0; /* current character */
-
- STATIC int xoff_flag=0,
- Timed_Out=0, /* we timed out before receiving character */
- Packet_Received=0, /* True if a Packet was received */
- masked=0; /* true if ctrl character was quoted */
-
- STATIC buf_type SA_Buf[Max_SA+1]; /* Send-ahead buffers */
-
- STATIC int SA_Next_to_ACK=0; /* Which SA_Buf is waiting for an ACK */
- STATIC int SA_Next_to_Fill=0; /* Which SA_Buf is ready for new data */
- STATIC int SA_Waiting=0; /* Number of SA_Buf's waiting for ACK */
- STATIC int Aborting=0; /* True if aborting the transfer ]*/
-
- STATIC unsigned char R_buffer[Max_Buf_Size];
- STATIC lstr filename=0; /* pathname */
- STATIC int S_Counter=0; /* Used to pace status update */
- STATIC int R_Counter=0;
- STATIC long S_Com_Data=0; /* Comm Port Data traffic */
- STATIC long R_Com_Data=0;
- STATIC long S_File_Data=0; /* File Data Traffic */
- STATIC long R_File_Data=0;
- STATIC long S_Packet_Count=0; /* Packet count */
- STATIC long R_Packet_Count=0;
- STATIC long S_Error_Count=0; /* Error count */
- STATIC long R_Error_Count=0;
- STATIC long S_File_Size=0; /* Length of file already sent */
- STATIC long R_File_Size=0; /* Length of file already received */
- STATIC long S_Remaining=0; /* # bytes remaining to be sent */
- STATIC long R_Remaining=0; /* # bytes reamining to be received */
- STATIC long Com_Rate=0; /* Comm. bytes per second */
- STATIC long Data_Rate=0; /* Effective Data bytes per second */
- STATIC long Time_Estimate=0; /* Estimated time until completion */
- STATIC int Resume_Flag=0; /* TRUE if attempting a DOW resume */
-
- /***************************************************************************/
- /*
- * crc
- *
- * Calculates XMODEM-style CRC (uses the CCITT V.41 polynomial but
- * completely backwards from the normal bit ordering).
- */
-
-
- STATIC unsigned crc_table[] = {
- 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
- 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
- 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
- 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
- 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
- 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
- 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
- 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
-
- 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
- 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
- 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
- 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
- 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
- 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
- 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
- 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
- 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
- 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
- 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
- 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
- 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
- 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
- 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
- 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
- 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
- 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
- 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
- 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
- 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
- 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
- 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
- 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
- };
-
- STATIC unsigned int crc_16;
-
- /*
- * Init_CRC initializes for XMODEM style CRC calculation by setting
- * crc_16 to value. Typically value is 0 for XMODEM and -1 for
- * B+ Protocl. It returns the initial value.
- */
- STATIC int Init_CRC (value)
- int value;
- {
- return( crc_16 = value );
- }
-
- /*
- Upd_CRC updates crc_16 and returns the updated value. */
-
- STATIC unsigned int Upd_CRC (value)
- unsigned int value;
- {
- crc_16 = crc_table [((crc_16 >> 8) ^ (value)) & 0xff] ^ (crc_16 << 8);
- return( crc_16 );
- }
- /***************************************************************************/
-
- STATIC void do_checksum (c)
- int c;
- {
- if (B_Plus && Use_CRC)
- checksum = Upd_CRC ((unsigned short)c);
- else
- {
- checksum = checksum << 1;
-
- if (checksum > 255)
- checksum = (checksum & 0xff) + 1;
-
- checksum += c;
-
- if (checksum > 255)
- checksum = (checksum & 0xff) + 1;
- }
- }
-
- STATIC void send_byte (ch)
- unsigned char ch;
- {
- Async_Send (ch);
- S_Com_Data++;
- S_Counter++;
- S_Counter = S_Counter % Port_Update_Rate;
-
- if (S_Counter == 0)
- ST_Display_Value (STComSent, S_Com_Data);
- }
-
- STATIC void send_masked_byte (ch)
- int ch;
- {
- ch &= 0xff;
-
- if (Quote_Table [ch] != 0)
- {
- send_byte (dle);
- send_byte (Quote_Table [ch]);
- }
- else
- send_byte (ch);
- }
-
- STATIC void Send_ACK()
- {
- send_byte (dle);
- send_byte (seq_num + '0');
- }
-
- STATIC void Send_NAK()
- {
- send_byte (nak);
- }
-
- /***********************
- STATIC void Send_ENQ()
- {
- send_byte (enq);
- }
- ***********************/
-
- STATIC int read_byte()
- {
- unsigned char chx;
- unsigned short Hiber;
- TIME_T start;
-
- Timed_Out = FALSE;
- start = gtime(NULL);
-
- if ( !Aborting )
- Hiber = 30;
- else
- Hiber = 10;
-
- while ( !Async_BuffeR_Check( &chx ) )
- {
-
- if (gtime(NULL) - start >= Hiber)
- {
- Timed_Out = TRUE;
- return( FALSE );
- }
- }
-
- ch = chx;
- R_Com_Data++;
- R_Counter++;
- R_Counter = R_Counter % Port_Update_Rate;
-
- if (R_Counter == 0 )
- ST_Display_Value (STComRead, R_Com_Data);
-
- return(TRUE);
- }
-
-
- STATIC int read_masked_byte()
- {
- masked = FALSE;
-
- if (read_byte() == FALSE)
- return(FALSE);
-
- if (ch == dle)
- {
- if (read_byte() == FALSE)
- return(FALSE);
-
- if (ch < 0x60)
- ch = ch & 0x1f;
- else
- ch = (ch & 0x1f) | 0x80;
-
- masked = TRUE;
- }
-
- return(TRUE);
- }
-
- /*
- Increment Sequence Number
- */
-
- STATIC int Incr_Seq (value)
- int value;
- {
- if (value == 9)
- return( 0);
- else
- return(value + 1);
- }
-
-
- STATIC int Read_Packet (Lead_in_Seen, From_Send_Packet)
- int Lead_in_Seen;
- int From_Send_Packet;
- /* Lead_in_Seen is true if the <DLE><B> has been seen already. */
-
-
- /* From_Send_Packet is true if called from Send_Packet */
- /* (causes exit on first error detected) */
-
- /* Returns True if Packet is available from host. */
-
- {
- short State,
- next_seq,
- block_num,
- errors,
- new_cks;
- int i;
- int NAK_Sent;
-
- if (Packet_Received) /* See if a Packet was picked up on a call to */
- /* Get_ACK */
- {
- Packet_Received = FALSE;
- return( TRUE);
- }
-
- NAK_Sent = FALSE;
-
- for( i=0; i<Buffer_Size; i++ )
- R_buffer[i] = 0;
-
- next_seq = (seq_num + 1) % 10;
- errors = 0;
-
- if (Lead_in_Seen) /* Start off on the correct foot */
- State = R_Get_Seq;
- else State = R_Get_DLE;
-
- while( TRUE )
- {
- ttime = 300;
-
- switch (State) {
-
- case R_Get_DLE :
- if (ST_Check_Abort() && !Aborting)
- {
- ST_Display_String (STMsg, "Aborting download per your request");
- Send_Failure ("AAborted by user");
- return(FALSE);
- }
-
- if ( !read_byte() )
- State = R_Timed_Out;
- else if ((ch & 0x7F) == dle )
- State = R_Get_B;
- else if ((ch & 0x7F) == enq )
- State = R_Send_ACK;
- break;
-
- case R_Get_B :
- if (!read_byte())
- State = R_Timed_Out;
- else if ((ch & 0x7F) == 'B')
- State = R_Get_Seq;
- else if (ch == enq)
- State = R_Send_ACK;
- else if (ch == ';')
- {
- ST_Display_Value (STComRead, R_Com_Data);
- State = R_Get_DLE;
- }
- else State = R_Get_DLE;
- break;
-
- case R_Get_Seq :
- if( Resume_Flag ) /* Improve status display for DOW resume */
- {
- e_timer = gtime(NULL);
- R_Com_Data = 2;
- }
- if (!read_byte())
- State = R_Timed_Out;
- else if (ch == enq)
- State = R_Send_ACK;
- else
- {
- if (B_Plus && Use_CRC)
- checksum = Init_CRC (0xffff);
- else checksum = 0;
-
- block_num = ch - '0';
-
- do_checksum (ch);
-
- i = 0;
- State = R_Get_Data;
- }
- break;
-
- case R_Get_Data :
- if (!read_masked_byte())
- State = R_Timed_Out;
- else if ((ch == etx) && !masked)
- {
-
- do_checksum (etx);
- State = R_Get_Check;
- }
- else
- {
- R_buffer[i] = ch;
- i = i + 1;
- do_checksum (ch);
- }
- break;
-
- case R_Get_Check :
- if (!read_masked_byte())
- State = R_Timed_Out;
- else
- {
- if (B_Plus && Use_CRC)
- {
- checksum = Upd_CRC ((unsigned int)ch);
-
- if (!read_masked_byte())
- new_cks = checksum ^ 0xff;
- else
- {
- checksum =
- Upd_CRC((unsigned int)ch);
- new_cks = 0;
- }
- }
- else new_cks = ch;
-
- if (new_cks != checksum)
- State = R_Timed_Out;
- else if (R_buffer[0] == 'F') /* Watch for Failure Packet */
- State = R_Success; /* which is accepted regardless */
- else if (block_num == seq_num) /* Watch for duplicate block */
- State = R_Send_ACK; /* Simply ACK it */
- else if (block_num != next_seq)
- State = R_Timed_Out; /* Bad seq num */
- else State = R_Success;
- }
- break;
-
- case R_Timed_Out :
- errors++;
-
- if ((errors > max_Errors) || (From_Send_Packet))
- return( FALSE );
-
- if (!NAK_Sent || !B_Plus)
- {
- R_Error_Count++;
- ST_Display_Value (STErrRead, R_Error_Count);
- NAK_Sent = TRUE;
- Send_NAK();
- }
-
- State = R_Get_DLE;
- break;
-
- case R_Send_ACK :
-
- if (!Aborting)
- Send_ACK();
-
- State = R_Get_DLE; /* wait for the next block */
- break;
-
- case R_Success :
- ST_Display_Value (STComRead, R_Com_Data);
- ST_Display_Value (STComSent, S_Com_Data);
-
- if (!Aborting)
- seq_num = block_num;
-
- R_Size = i;
- R_Packet_Count++;
- ST_Display_Value (STPacRead, R_Packet_Count);
- return(TRUE);
-
- }
- }
-
- } /* Read_Packet */
-
- STATIC void Send_Data (BuffeR_Number)
- int BuffeR_Number;
- {
- int i;
- buf_type *p;
-
- p = &SA_Buf [BuffeR_Number];
-
- if (B_Plus && Use_CRC)
- checksum = Init_CRC (0xffff);
- else checksum = 0;
-
- send_byte (dle);
- send_byte ('B');
-
- send_byte (p->seq + '0');
- do_checksum (p->seq + '0');
-
- for (i = 0; i<=p->num; i++ )
- {
- send_masked_byte (p->buf [i]);
- do_checksum (p->buf[i]);
- }
-
- send_byte (etx);
- do_checksum (etx);
-
- if (B_Plus && Use_CRC)
- send_masked_byte (checksum >> 8);
-
- send_masked_byte (checksum);
-
- }
-
- STATIC int Incr_SA (Old_Value)
- int Old_Value;
- {
- if (Old_Value == Max_SA)
- return(0);
- else
- return(Old_Value + 1);
- }
-
- /*
- ReSync is called to restablish syncronism with the remote. This is
- accomplished by sending <ENQ><ENQ> and waiting for the sequence
- <DLE><d><DLE><d> to be received, ignoring everything else.
-
- Return is -1 on time out, `B` if <DLE><B> seen, else the digit <d>.
- */
-
- STATIC int ReSync()
- #define Get_First_DLE 1
- #define Get_First_Digit 2
- #define Get_Second_DLE 3
- #define Get_Second_Digit 4
- {
- int State,
- Digit_1;
-
- send_byte (enq); /* Send <ENQ><ENQ> */
- send_byte (enq);
- State = Get_First_DLE;
-
- while(1)
- {
- switch (State) {
- case Get_First_DLE :
- if (!read_byte())
- return(-1);
-
- if (ch == dle)
- State = Get_First_Digit;
- break;
-
- case Get_First_Digit :
- if (!read_byte())
- return(-1);
-
- if ((ch >= '0') && (ch <= '9'))
- {
- Digit_1 = ch;
- State = Get_Second_DLE;
- }
- else if (ch == 'B')
- return( ch );
- break;
-
- case Get_Second_DLE :
- if (!read_byte())
- return(-1);
-
- if (ch == dle)
- State = Get_Second_Digit;
- break;
-
- case Get_Second_Digit :
- if (!read_byte())
- return(-1);
-
- if ((ch >= '0') && (ch <= '9'))
- {
- if (Digit_1 == ch )
- return(ch);
- else if (ch == 'B')
- return( ch );
- else
- {
- Digit_1 = ch;
- State = Get_Second_DLE;
- }
- }
- else State = Get_Second_DLE;
- break;
-
- } /* case */
- } /* while TRUE */
- }
-
- /*
- Get_ACK is called to wait until the SA_Buf indicated by SA_Next_to_ACK
- has been ACKed by the host.
- */
-
- STATIC int Get_ACK()
- {
- int State,
- errors,
- block_num,
- i;
- /* int new_cks;*/
- int Sent_ENQ;
- int SA_Index;
-
- Packet_Received = FALSE;
- errors = 0;
- Sent_ENQ = FALSE;
- State = S_Get_DLE;
-
- while(1)
- {
- switch (State) {
- case S_Get_DLE :
- ttime = 300;
-
- if (ST_Check_Abort() && !Aborting)
- {
- ST_Display_String (STMsg,
- "Aborting the upload per your request");
- Send_Failure ("AAborted by user");
- return(FALSE);
- }
-
- if (!read_byte() )
- State = S_Timed_Out;
- else
- {
- if (ch == dle)
- State = S_Get_Num;
- else if (ch == nak )
- State = S_Send_ENQ;
- else if (ch == etx )
- State = S_Send_NAK;
- }
- break;
-
- case S_Get_Num :
- if (!read_byte() )
- State = S_Timed_Out;
- else if ((ch >= '0') && (ch <= '9'))
- State = S_Have_ACK; /* Received ACK */
- else if (ch == 'B' )
- {
- if (!Aborting)
- State = S_Get_Packet; /* Try to receive a Packet */
- else State = S_Skip_Packet; /* Try to skip a Packet */
- }
- else if (ch == nak)
- State = S_Send_ENQ;
- else if (ch == ';')
- { /* Received a WACK (Wait Acknowledge) */
- ST_Display_Value (STComRead, R_Com_Data);
- State = S_Get_DLE;
- }
- else State = S_Timed_Out;
- break;
-
- case S_Get_Packet :
- if (Read_Packet (TRUE, TRUE) )
- {
- Packet_Received = TRUE;
-
- if (R_buffer [0] == 'F') /* Check for Failure Packet */
- {
- Send_ACK();
- return(FALSE);
- }
-
- State = S_Get_DLE; /* Stay here to find the ACK */
- }
- else State = S_Get_DLE; /* Receive failed; keep watching for ACK */
- break;
-
- case S_Skip_Packet : /* Skip an incoming Packet */
- if (!read_byte())
- State = S_Timed_Out;
- else if (ch == etx )
- { /* Get the Checksum or CRC */
- if (!read_masked_byte())
- State = S_Timed_Out;
- else if (!Use_CRC)
- State = S_Get_DLE;
- else if (!read_masked_byte())
- State = S_Timed_Out;
- else State = S_Get_DLE;
- }
- break;
-
- case S_Have_ACK :
- block_num = ch - '0';
- ST_Display_Value (STComSent, S_Com_Data);
- ST_Display_Value (STComRead, R_Com_Data);
-
- if (SA_Buf [SA_Next_to_ACK].seq == block_num )
- { /* This is the one we're waiting for */
- SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
- SA_Waiting = SA_Waiting - 1;
-
- if (SA_Error_Count > 0 ) /* Apply heuristic to control */
- SA_Error_Count--; /* Upload Performance degradation */
-
- return(TRUE);
- }
- else if ((SA_Buf [Incr_SA (SA_Next_to_ACK)].seq == block_num) &&
- SA_Waiting == 2)
- { /* Must have missed an ACK */
- SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
- SA_Next_to_ACK = Incr_SA (SA_Next_to_ACK);
- SA_Waiting = SA_Waiting - 2;
-
- if (SA_Error_Count > 0)
- SA_Error_Count--;
-
- return(TRUE);
- }
- else if (SA_Buf [SA_Next_to_ACK].seq == Incr_Seq (block_num) )
- {
- if (Sent_ENQ)
- State = S_Send_Data; /* Remote missed first block */
- else State = S_Get_DLE; /* Duplicate ACK */
- }
- else
- {
- if (!Aborting) /* While aborting, ignore any */
- State = S_Timed_Out; /* ACKs that have been sent */
- else State = S_Get_DLE; /* which are not for the failure */
- } /* Packet. */
-
- Sent_ENQ = FALSE;
- break;
-
- case S_Timed_Out :
- State = S_Send_ENQ;
- break;
-
- case S_Send_NAK :
- errors++;
- S_Error_Count++;
- ST_Display_Value (STErrSent, S_Error_Count);
-
- if (errors > max_Errors)
- return(FALSE);
-
- Send_NAK();
-
- State = S_Get_DLE;
- break;
-
- case S_Send_ENQ :
- errors++;
- S_Error_Count++;
- ST_Display_Value (STErrSent, S_Error_Count);
-
- if ((errors > max_Errors) || (Aborting && (errors > 3)))
- return(FALSE);
-
- ch = ReSync();
- if (ch == -1)
- State = S_Get_DLE;
- else if (ch == 'B')
- {
- if( !Aborting )
- State = S_Get_Packet; /* Try to receive a Packet */
- else
- State = S_Skip_Packet; /* Try to skip a Packet */
- }
- else State = S_Have_ACK;
- Sent_ENQ = TRUE;
- break;
-
- case S_Send_Data :
- SA_Error_Count += 3;
-
- if (SA_Error_Count >= 12) /* Stop Upload Send Ahead if too many */
- SA_Max = 1; /* errors have occured */
-
- SA_Index = SA_Next_to_ACK;
-
- for (i = 1; i<=SA_Waiting; i++ )
- {
- Send_Data (SA_Index);
- SA_Index = Incr_SA (SA_Index);
- }
-
- State = S_Get_DLE;
- Sent_ENQ = FALSE;
- break;
- }
- }
- } /* Get_ACK */
-
- STATIC int send_Packet (size)
- int size;
- {
- while (SA_Waiting >= SA_Max) /* Allow for possible drop out of Send Ahead */
- {
- if (!Get_ACK() )
- return(FALSE);
- }
-
- seq_num = Incr_Seq (seq_num);
- SA_Buf [SA_Next_to_Fill].seq = seq_num;
- SA_Buf [SA_Next_to_Fill].num = size;
- Send_Data (SA_Next_to_Fill);
- SA_Next_to_Fill = Incr_SA (SA_Next_to_Fill);
- SA_Waiting = SA_Waiting + 1;
- S_Packet_Count++;
- ST_Display_Value (STComSent, S_Com_Data);
- ST_Display_Value (STPacSent, S_Packet_Count);
- return(TRUE);
- }
-
- /*
- SA_Flush is called after sending the last Packet to get host's
- ACKs on outstanding Packets.
- */
-
- STATIC int SA_Flush()
- {
- while (SA_Waiting > 0)
- {
- if (!Get_ACK())
- return(FALSE);
- }
- return( TRUE );
- }
-
- STATIC void Send_Failure (Reason)
- char Reason[];
- {
- int i;
- buf_type *p;
-
- SA_Next_to_ACK = 0;
- SA_Next_to_Fill = 0;
- SA_Waiting = 0;
- Aborting = TRUE; /* Inform Get_ACK we're aborting ]*/
-
- p = &SA_Buf [0];
- p->buf [0] = 'F';
- for (i = 1; i<=strlen(Reason); i++ )
- p->buf [i] = (Reason [i]);
-
- if ( send_Packet (strlen(Reason)) )
- SA_Flush(); /* Gotta wait for the Initiator to ACK it */
- }
-
- /* Send_File is called to send a file to the host */
-
- STATIC int Send_File (name)
- char name[];
- {
- int n;
- FILE *data_File;
- buf_type *p;
-
- data_File = fopen (name,"rb");
-
- if (data_File == 0 )
- {
- ST_Display_String (STMsg, "Cannot find that file");
- Send_Failure ("MFile not found");
- return(FALSE);
- }
-
- fseek(data_File,0L,2); /* seek to end of file */
- S_Remaining = ftell(data_File); /* how long is this file ? */
- fseek(data_File,0L,0); /* back to the start, ready to go */
- ST_Display_Value (STUplRem, S_Remaining);
- /* Send_File_Information here ? */
-
- /*----------------
- S_Com_Data = 0;
- R_Com_Data = 0;
- e_timer = gtime(NULL);
- -------------------*/
- do
- {
- p = &SA_Buf [SA_Next_to_Fill];
- p->buf [0] = 'N';
- n = fread (&p->buf[1], 1, Buffer_Size, data_File);
-
- if (n > 0)
- {
- if (send_Packet (n) == FALSE)
- {
- fclose(data_File);
- return(FALSE);
- }
-
- S_File_Data = S_File_Data + (n);
- S_File_Size = S_File_Size + (n);
- S_Remaining = S_Remaining - (n);
- ST_Display_Value (STUplSize, S_File_Size);
- ST_Display_Value (STDataSent, S_File_Data);
- ST_Display_Value (STUplRem, S_Remaining);
- Time_Estimate = gtime(NULL) - e_timer;
- ST_Display_Value (STElapsed, Time_Estimate);
-
- if (Time_Estimate != 0)
- {
- Com_Rate = S_Com_Data / Time_Estimate;
- Data_Rate = S_File_Data / Time_Estimate;
- ST_Display_Value (STComRate, Com_Rate);
- ST_Display_Value (STDataRate, Data_Rate);
-
- if (Data_Rate != 0)
- {
- Time_Estimate = S_Remaining / Data_Rate;
- ST_Display_Value (STRemTime, Time_Estimate);
- }
- }
- }
- } while(n > 0);
-
- if (ferror(data_File) != 0)
- {
- Send_Failure ("EFile read failure");
- ST_Display_String (STMsg, "Read failure...aborting");
- fclose(data_File);
- return(FALSE);
- }
-
- /* Inform host that the file was sent */
-
- p = &SA_Buf [SA_Next_to_Fill];
- p->buf [0] = 'T';
- p->buf [1] = 'C';
-
- if (send_Packet (2) == FALSE)
- {
- fclose (data_File);
- return(FALSE);
- }
- else
- {
- fclose (data_File);
- if (!SA_Flush())
- return(FALSE);
- return(TRUE);
- }
-
- } /* Send_File */
-
- /*
- Do_Transport_Parameters is called when a Packet type of + is received.
- It sends a Packet of Our local B Plus parameters and sets the Our_xx
- parameters to the minimum of the Initiator's and Our own parameters.
- */
-
- STATIC void Do_Transport_Parameters()
- {
- int Quote_Set_Present;
- int i;
- buf_type *p;
-
- if (BP_Special_Quoting)
- {
- for( i=0; i<8; i++ )
- Our_QS[i] = BP_Special_Quote_Set[i];
- }
- else
- {
- for( i=0; i<8; i++ )
- Our_QS[i] = DQ_Minimal[i];
- }
-
- for (i = R_Size + 1; i<=512; i++ ) R_buffer [i] = 0;
-
- His_WS = R_buffer [1]; /* Pick out Initiator's parameters */
- His_WR = R_buffer [2];
- His_BS = R_buffer [3];
- His_CM = R_buffer [4];
-
- His_QS [0] = R_buffer [7];
- His_QS [1] = R_buffer [8];
- His_QS [2] = R_buffer [9];
- His_QS [3] = R_buffer [10];
- His_QS [4] = R_buffer [11];
- His_QS [5] = R_buffer [12];
- His_QS [6] = R_buffer [13];
- His_QS [7] = R_buffer [14];
-
- His_DR = R_buffer [15];
- His_UR = R_buffer [16];
- His_FI = R_buffer [17];
-
- if (R_Size >= 14)
- Quote_Set_Present = TRUE;
- else Quote_Set_Present = FALSE;
-
- p = &SA_Buf [SA_Next_to_Fill];
- p->buf [0] = '+'; /* Prepare to return Our own parameters */
- p->buf [1] = Def_WS;
- p->buf [2] = Def_WR;
- p->buf [3] = Def_BS;
- p->buf [4] = Def_CM;
- p->buf [5] = Def_DQ;
- p->buf [6] = 0; /* No transport layer here */
-
- for (i = 0; i<=7; i++ )
- p->buf [i + 7] = Our_QS [i];
-
- if (BP_Auto_Resume) /* Set Download Resume according to */
- Def_DR = 2; /* user's preference */
- else Def_DR = 1;
-
- p->buf [15] = Def_DR;
- p->buf [16] = Def_UR;
- p->buf [17] = Def_FI;
-
- Update_Quote_Table (DQ_Full); /* Send the + Packet w/ full quoting */
-
- if (!send_Packet (17) )
- return;
-
- if (SA_Flush()) /* Wait for host's ACK on Our Packet */
- {
- if (His_WS < Def_WR) /* Take minimal subset of Transport Params. */
- Our_WR = His_WS; /* If he can send ahead, we can receive it. */
- else Our_WR = Def_WR;
-
- if (His_WR < Def_WS) /* If he can receive send ahead, we can send it. */
- Our_WS = His_WR;
- else Our_WS = Def_WS;
-
-
- if( His_BS < Def_BS)
- Our_BS = His_BS;
- else Our_BS = Def_BS;
-
- if (His_CM < Def_CM)
- Our_CM = His_CM;
- else Our_CM = Def_CM;
-
- if (His_DR < Def_DR)
- Our_DR = His_DR;
- else Our_DR = Def_DR;
-
- if (His_UR < Def_UR)
- Our_UR = His_UR;
- else Our_UR = Def_UR;
-
- if (His_FI < Def_FI)
- Our_FI = His_FI;
- else Our_FI = Def_FI;
-
- if (Our_BS == 0)
- Our_BS = 4; /* Default */
-
- Buffer_Size = Our_BS * 128;
-
- B_Plus = TRUE;
-
- if (Our_CM == 1)
- Use_CRC = TRUE;
-
- if (Our_WS != 0)
- SA_Max = Max_SA;
- }
-
- Clear_Quote_Table(); /* Restore Our Quoting Set */
- Update_Quote_Table (Our_QS);
-
- if (Quote_Set_Present) /* Insert Initiator's Quote Set */
- Update_Quote_Table (His_QS);
- }
-
- /* Check_Keep is called from Receive_File when a fatal error */
- /* occurs. It asks the user if the file should be retained */
-
- STATIC void Check_Keep (data_File, Name)
- FILE *data_File;
- char Name[];
- {
- char yn;
- char str[80];
-
- fclose (data_File);
-
- if ((!BP_Auto_Resume) || (!B_Plus) || (Our_DR == 0))
- {
- strcpy( str, "Do you wish to retain the partial " );
- strcat( str, Name );
- strcat( str, "?" );
- ST_Yes_or_No( str, &yn );
- }
- else
- yn = 'Y';
-
- if (yn == 'N')
- {
- unlink ( Name );
- ST_Display_String (STMsg, "File erased.");
- }
- else
- {
- /* implementation dependent option: Hide the file from casual view */
- ST_Display_String (STMsg, "File retained.");
- }
- }
-
- /* Process_File_Information is called from Receive_File when a TI Packet */
- /* is received. It extracts the desired information from the Packet. */
-
- STATIC char Val_Str[50];
- STATIC int e_i=0, e_j=0, e_n=0;
-
- STATIC void Extract_String() /* Extract next string of characters */
- {
- int Digit_Seen;
-
- Digit_Seen = FALSE;
- e_j = 0;
- while (e_i <= e_n)
- {
- if ((R_buffer [e_i] >= '0') && (R_buffer [e_i] <= '9') )
- {
- Digit_Seen = TRUE;
- e_j++;
- Val_Str [e_j] = R_buffer [e_i];
- }
- else if (Digit_Seen)
- {
- Val_Str [0] = e_j;
- return;
- }
-
- e_i++;
- }
- }
-
- STATIC void Process_File_Information()
- {
- int i;
-
- e_n = R_Size - 1;
- e_i = 4; /* Skip data type and compression flag */
- Extract_String();
- /* Val (Val_Str, R_Remaining, e_j); */
- R_Remaining = 0;
- for( i=1; i<=e_j; i++ )
- R_Remaining = (R_Remaining * 10) + (Val_Str[i] - '0');
- R_Remaining = R_Remaining - R_File_Size; /* Adjust for Dow Resume */
- ST_Display_Value (STDowRem, R_Remaining);
-
- /* Ignore rest of parameters for now */
-
- S_Packet_Count = 0;
- R_Packet_Count = 0;
- }
-
- /* Receive_File is called to receive a file from the host */
-
- STATIC int Receive_File (Name)
- char Name[];
- {
- FILE *Data_File;
- int status;
- long File_Length; /* For download resumption */
- lstr Work_String;
- int Packet_Len;
- int i, n;
- char yn;
- char Dow_Type;
- buf_type *p;
-
- Dow_Type = 'D'; /* Assume normal downloading */
-
- Data_File = fopen( Name, "rwb" ); /* open for r/w first */
-
- if (Data_File != NULL) /* this file already exists */
- { /* See if we can try automatic resume */
- if ((Our_DR > 1) && BP_Auto_Resume)
- Dow_Type = 'R'; /* Remote supports `Tf', let's try */
- else if ((Our_DR > 0))
- {
- ST_Display_String (STMsg, "File already exists.");
- ST_Yes_or_No ("Do you wish to resume downloading? ", &yn);
-
- if (yn == 'Y')
- Dow_Type = 'R';
- else
- ST_Display_String (STMsg, "File being overwritten.");
- }
- }
-
- switch( Dow_Type ) {
- case 'D':
- if( Data_File )
- fclose( Data_File ); /* close the read/write file */
- Data_File = fopen( Name, "wb" ); /* open for write */
- if (Data_File == NULL)
- {
- Send_Failure ("CCannot create file");
- return(FALSE);
- }
- Send_ACK();
- break;
-
- case 'R' :
- /* Resume download */
- /* file is open and at start */
- ST_Display_String (STMsg, "Calculating CRC");
-
- p = &SA_Buf [SA_Next_to_Fill];
- if (Dow_Type == 'R')
- {
- checksum = Init_CRC (0xffff);
- do {
- n = fread (&p->buf [0], 1, Buffer_Size,
- Data_File);
- for (i = 0; i<n; i++ )
- checksum =
- Upd_CRC((unsigned int)p->buf [i]);
- } while( n > 0 );
- }
- else
- checksum = 0;
-
- p->buf [0] = 'T';
- p->buf [1] = 'r';
-
- Packet_Len = 2;
- File_Length = ftell(Data_File);
-
- ltoa (File_Length, Work_String);
- strcat( Work_String, " " );
-
- for (i = 0; i<strlen(Work_String); i++ )
- {
- p->buf [Packet_Len] = Work_String [i];
- Packet_Len++;
- }
-
- ltoa ((long)checksum, Work_String);
- strcat( Work_String, " " );
-
- for (i = 0; i<strlen(Work_String); i++ )
- {
- p->buf [Packet_Len] = Work_String [i];
- Packet_Len++;
- }
-
- if (!send_Packet (Packet_Len - 1)) /* Send_Data sends 0..Size */
- {
- fclose (Data_File);
- return(FALSE);
- }
-
- if (!SA_Flush())
- {
- fclose (Data_File);
- return(FALSE);
- }
-
- R_File_Size = File_Length;
- ST_Display_Value (STDowSize, R_File_Size);
- ST_Display_String (STMsg, "Host calculating CRC...");
- Resume_Flag = TRUE;
- break;
- }
-
-
- /*
- Process each incoming Packet until 'TC' Packet received or failure
- */
-
- R_Packet_Count = 0;
- S_Packet_Count = 0;
-
- if( BP_Use_File_Size )
- R_Remaining = BP_File_Size;
- else
- R_Remaining = 0;
- while(TRUE)
- {
- if (Read_Packet (FALSE, FALSE))
- {
- switch (R_buffer[0]) {
- case 'N' :
- if( Resume_Flag )
- {
- ST_Display_String( STMsg, "Resuming Download" );
- Resume_Flag = FALSE;
- }
-
- status = fwrite( &R_buffer[1], 1, R_Size - 1, Data_File );
-
- if ((status != (R_Size - 1)))
- {
- ST_Display_String (STMsg, "Write failure...aborting");
- Send_Failure ("EWrite failure");
- Check_Keep (Data_File, Name);
- return(FALSE);
- }
- R_File_Data = R_File_Data + (R_Size - 1);
- ST_Display_Value (STDataRead, R_File_Data);
- R_File_Size = R_File_Size + (status);
- ST_Display_Value (STDowSize, R_File_Size);
-
- Time_Estimate = gtime(NULL) - e_timer;
- ST_Display_Value (STElapsed, Time_Estimate);
-
- if (Time_Estimate != 0)
- {
- Com_Rate = R_Com_Data / Time_Estimate;
- Data_Rate = R_File_Data / Time_Estimate;
- ST_Display_Value (STComRate, Com_Rate);
- ST_Display_Value (STDataRate, Data_Rate);
- }
- else Data_Rate = 0;
-
- if (R_Remaining != 0)
- /* Decrement remaining byte count */
- {
- R_Remaining = R_Remaining - (R_Size - 1);
- ST_Display_Value (STDowRem, R_Remaining);
-
-
- if (Data_Rate != 0)
- {
- Time_Estimate = R_Remaining / Data_Rate;
- ST_Display_Value (STRemTime, Time_Estimate);
- }
- }
-
-
- Send_ACK();
- break;
-
- case 'T' :
- if (R_buffer[1] == 'C')
- {
- ST_Display_String (STMsg, "*** Transfer Complete ***");
- status = fclose (Data_File);
-
- if (status == EOF)
- {
- ST_Display_String (STMsg, "Failure during close...aborting");
- Send_Failure ("EError during close");
- Check_Keep (Data_File, Name);
- return(FALSE);
- }
-
- Send_ACK();
- return(TRUE);
- }
- else if (R_buffer [1] == 'I')
- {
- Send_ACK();
- Process_File_Information();
- }
- else if ((R_buffer [1] == 'f') && BP_Auto_Resume)
- /* `Tf' Packet implies host failed the */
- { /* CRC check on a DOW resume */
- fclose (Data_File); /* So...replace the file */
- Data_File = fopen(Name, "wb");
- if (Data_File == NULL)
- {
- Send_Failure ("CCannot create file");
-
- ST_Display_String (STMsg,
- "CRC check failed; cannot create file");
- return(FALSE);
- }
-
- if (Our_FI != 0 || BP_Use_File_Size)
- R_Remaining = R_Remaining + R_File_Size;
-
- R_File_Size = 0;
- ST_Display_String (STMsg, "CRC check failed; overwriting file");
- Resume_Flag = FALSE;
- e_timer = gtime(NULL);
- S_Com_Data = 0;
- R_Com_Data = 0;
- Send_ACK();
- }
- else
- {
- ST_Display_String (STMsg, "Invalid termination Packet...aborting");
- Send_Failure ("NInvalid T Packet");
- Check_Keep (Data_File, Name);
- return(FALSE);
- }
- break;
-
- case 'F' :
- Send_ACK();
- ST_Display_String (STMsg, "Failure Packet received...aborting");
- Check_Keep (Data_File, Name);
- return(FALSE);
-
- }
-
- }
- else
- {
- if (!Aborting)
- ST_Display_String (STMsg, "Download failure");
- Check_Keep (Data_File, Name);
- return(FALSE);
- }
- }
-
- } /* Receive_File */
-
- /* =================================================================== */
-
- void BP_DLE_Seen()
- { /* DLE_Seen */
-
- int i;
-
- /*
- Begin by getting the next character. If it is <B> then enter the
- B_Protocol state. Otherwise simply return.
- */
-
- Port_Update_Rate = 30;
-
- ST_Initialize();
-
- if (!read_byte())
- return;
-
-
- if (ch != 'B')
- return;
-
- SA_Next_to_ACK = 0; /* Initialize Send-ahead variables */
- SA_Next_to_Fill = 0;
- SA_Waiting = 0;
- Aborting = FALSE;
- Packet_Received = FALSE;
-
- /* Establish Data Block Size as a function of the Baud */
- /* The intent is to keep the per-Packet time to 4-5 seconds */
-
- PortBps = bps; /* Apend FMR version */
-
- switch (PortBps) {
- case bps300:
- Def_BS = 1;
- Port_Update_Rate = 30;
- break;
- case bps600:
- case bps1200:
- Def_BS = 4;
- Port_Update_Rate = 120;
- break;
- case bps2400:
- case bps4800:
- case bps9600:
- Def_BS = 8;
- Port_Update_Rate = 240;
- break;
- }
-
- /* <DLE><B> received; begin B Protocol */
-
- xoff_flag = TRUE;
-
- R_Counter = 0;
- S_Counter = 0;
- R_File_Data = 0;
- S_File_Data = 0;
- R_Com_Data = 0;
- S_Com_Data = (0);
- S_Packet_Count = (0);
- R_Packet_Count = (0);
- S_File_Size = (0);
- R_File_Size = (0);
- S_Error_Count = (0);
- R_Error_Count = (0);
- Resume_Flag = FALSE;
-
- if (Read_Packet (TRUE, FALSE))
- {
- /* Dispatch on the type of Packet just received */
-
- switch (R_buffer[0]) {
- case 'T': /* File Transfer Application */
- /* ST_Initialize();*/
- ST_Display_Value (STComRead, R_Com_Data);
- S_Com_Data = 0;
- R_Com_Data = 0;
- e_timer = gtime(NULL);
-
- switch (R_buffer[1]) {
- case 'D' :
- ST_Display_String (STUpDow, "Downloading ");
- break;
- case 'U' :
- ST_Display_String (STUpDow, "Uploading ");
- break;
- default:
- ST_Display_String (STMsg, "Unimplemented Transfer Function");
- Send_Failure ("NUnimplemented Transfer function");
- ST_Terminate();
- return;
- }
-
- switch (R_buffer[2]) {
- case 'A':
- ST_Display_String (STType, "ASCII");
- break;
- case 'B':
- ST_Display_String (STType, "Binary");
- break;
- default:
- ST_Display_String (STMsg, "Unimplemented File Type");
- Send_Failure ("NUnimplemented file type");
- ST_Terminate();
- return;
- }
-
- i = 2;
- filename[0] = '\0';
-
- while ( R_buffer[i] != 0 ) {
- if ( i >= (R_Size - 1)) {
- filename[i - 2] = '\0';
- break;
- }
- i++;
- filename[i-3] = R_buffer[i];
- }
-
- ST_Display_String (STFile, filename);
- S_Packet_Count = (0);
- R_Packet_Count = (0);
-
- if (R_buffer[1] == 'U')
- Send_File (filename);
- else
- Receive_File (filename);
-
- ST_Terminate();
- break;
-
- case '+': /* Received Transport Parameters Packet */
- Do_Transport_Parameters();
- break;
-
- default:
- /* Unknown Packet; tell the host we don't know */
- Send_Failure ("NUnknown Packet Type");
- break;
-
- } /* of case */
-
- } /* of if Read_Packet then*/
- } /* DLE_Seen */